Skip to content

fix(MAVLink/Signing): refresh signing timestamp from wall clock#14430

Draft
HTRamsey wants to merge 1 commit into
mavlink:masterfrom
HTRamsey:fix/signing-timestamp-wallclock-refresh
Draft

fix(MAVLink/Signing): refresh signing timestamp from wall clock#14430
HTRamsey wants to merge 1 commit into
mavlink:masterfrom
HTRamsey:fix/signing-timestamp-wallclock-refresh

Conversation

@HTRamsey
Copy link
Copy Markdown
Member

Summary

Fixes #14375 — MAVLink signing: GCS fails to connect when SITL is already running.

Root cause

SigningChannel::init() seeds _signing.timestamp from wall clock once. After that, libmavlink's mavlink_sign_packet only advances the value by +1 per outbound packet — it does not track real time. When wall-clock time elapses between init() and the next signed send (e.g. QGC starts, sits idle waiting to detect the vehicle, then sends its first command), the wire timestamp drifts behind real wall-clock. Peers that pin their signing.timestamp to wall clock (ArduPilot's GCS_Signing::update_signing_timestamp) then reject the packet as OLD_TIMESTAMP, which is the exact symptom in #14375 (~3-minute offset matching the SITL-uptime-before-QGC-start window).

Fix

  • SigningChannel::refreshOutgoingTimestamp() — bumps _signing.timestamp up to current wall-clock under the write lock; no-op when disabled or already ahead.
  • SigningController — owns a 1 Hz QTimer that drives the refresh for the controller's lifetime. 1 Hz is well under the receiver's 6 s MAVLINK_SIGNING_TIMESTAMP_LIMIT window.
  • Mirrors ArduPilot's GCS_Signing::update_signing_timestamp() pattern.

Test plan

  • SigningTest (29/29 pass) — including new regression _testRefreshOutgoingTimestamp that simulates the 3-minute stall, verifies the refresh catches up, no-ops when ahead of wall clock, and no-ops when disabled.
  • MockLinkSigningTest (8/8 pass) — no regression in enable/disable FSM.
  • SigningControllerTest (30/30 pass) — no regression in burst-alert / auto-detect / state machine.
  • Manual: ArduPilot SITL with signing key, start SITL → wait 3 min → start QGC → confirm initialisation commands succeed.

libmavlink only increments signing->timestamp by +1 per outbound packet,
so idle gaps between SigningChannel::init() and the next signed send
cause the wire timestamp to drift behind wall clock. Peers that pin
their signing.timestamp to wall clock (ArduPilot) then reject the
packet as OLD_TIMESTAMP.

Add SigningChannel::refreshOutgoingTimestamp() that bumps the channel
timestamp up to the current wall clock, and drive it from a 1 Hz timer
in SigningController — well under MAVLINK_SIGNING_TIMESTAMP_LIMIT (6 s
on the receiver). Mirrors ArduPilot's GCS_Signing::update_signing_timestamp().

Fixes mavlink#14375
@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

Codecov Report

❌ Patch coverage is 64.28571% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.45%. Comparing base (f29efd3) to head (9b62660).
⚠️ Report is 30 commits behind head on master.

Files with missing lines Patch % Lines
src/MAVLink/Signing/SigningController.cc 25.00% 0 Missing and 3 partials ⚠️
src/MAVLink/Signing/SigningChannel.cc 80.00% 0 Missing and 2 partials ⚠️

❌ Your project check has failed because the head coverage (26.45%) is below the target coverage (30.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #14430      +/-   ##
==========================================
+ Coverage   25.47%   26.45%   +0.98%     
==========================================
  Files         769      767       -2     
  Lines       65912    66299     +387     
  Branches    30495    30674     +179     
==========================================
+ Hits        16788    17539     +751     
+ Misses      37285    36312     -973     
- Partials    11839    12448     +609     
Flag Coverage Δ
unittests 26.45% <64.28%> (+0.98%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/MAVLink/Signing/SigningChannel.h 66.66% <ø> (ø)
src/MAVLink/Signing/SigningController.h 100.00% <ø> (ø)
src/MAVLink/Signing/SigningChannel.cc 62.80% <80.00%> (+1.54%) ⬆️
src/MAVLink/Signing/SigningController.cc 53.10% <25.00%> (-0.45%) ⬇️

... and 131 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c17948f...9b62660. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

Build Results

Platform Status

Platform Status Details
Linux Passed View
Windows Passed View
MacOS Passed View
Android Passed View

All builds passed.

Pre-commit

Check Status Details
pre-commit Failed (non-blocking) View

Pre-commit hooks: 2 passed, 42 failed, 7 skipped.

Test Results

linux-coverage: 88 passed, 0 skipped
Total: 88 passed, 0 skipped

Code Coverage

Coverage: 60.4%

No baseline available for comparison

Artifact Sizes

Artifact Size
QGroundControl 216.77 MB
QGroundControl-aarch64 176.66 MB
QGroundControl-installer-AMD64 134.67 MB
QGroundControl-installer-AMD64-ARM64 77.29 MB
QGroundControl-installer-ARM64 106.03 MB
QGroundControl-linux 186.86 MB
QGroundControl-mac 186.86 MB
QGroundControl-windows 186.87 MB
QGroundControl-x86_64 172.33 MB
No baseline available for comparison

Updated: 2026-05-22 21:06:44 UTC • Triggered by: Android

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MAVLink signing: GCS fails to connect when SITL is already running

1 participant